package lectores;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLException;
import java.sql.Statement;
import javax.xml.parsers.ParserConfigurationException;
import lectores.parsersXLSX.ProcesadorXLSX;
import lectores.parsersXLSX.XLSXHandler;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackageAccess;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.xssf.eventusermodel.ReadOnlySharedStringsTable;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.model.StylesTable;
import org.xml.sax.SAXException;

public class LectorConveniosPrimaDevengada extends LectorConvenios {
    
    private File archivoExcel;
    private Workbook libroConveniosPrimaDevengada;
    private int mesSeleccionado;
    private int tipoFiltroPeriodo;
    private final int[] INDICES_DATOS_VALIDOS = {0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 16, 23};
    private String queryCampos = "INSERT INTO convenios_pd(PERIODO, ID_AGENTE, NOMBRE_AGENTE, SISTEMA_ORIGEN,"
                + " ID_RAMO_CONTABLE, RAMO_CONTABLE, ID_SUBRAMO, SUBRAMO, ID_PROMOTORIA, PROMOTORIA, IMP_PMA_RIESGO_DEV,"
                + " MARCA, RAMO, COLUMNA)";
    private boolean metioRegistroMes = false;
    private Statement st;
    
    public LectorConveniosPrimaDevengada(File archivoExcel, int mesSeleccionado, int tipoFiltroPeriodo, Statement st)
            throws SQLException, InvalidFormatException, IOException, SAXException, OpenXML4JException, ParserConfigurationException, ExcelMalFormadoException {
        this.archivoExcel = archivoExcel;
        this.mesSeleccionado = mesSeleccionado;
        this.tipoFiltroPeriodo = tipoFiltroPeriodo;
        this.st = st;
        creaMapeoDañosVida();
        creaMapeoColumnas();
        cargaArchivo();
    }
    
    void cargaArchivo() throws SQLException, InvalidFormatException, IOException, SAXException, OpenXML4JException, ParserConfigurationException, ExcelMalFormadoException {
        creaTablaConvenios();
        
        if(archivoExcel.getPath().endsWith(".xlsx")) {
            OPCPackage paqueteExcel = OPCPackage.open(archivoExcel.getPath(), PackageAccess.READ);
            ReadOnlySharedStringsTable strings = new ReadOnlySharedStringsTable(paqueteExcel);
            XSSFReader xssfReader = new XSSFReader(paqueteExcel);
            StylesTable styles = xssfReader.getStylesTable();
            XLSXHandler manejadorContenido = new XLSXHandler(styles, strings, this, mesSeleccionado, tipoFiltroPeriodo);
            ProcesadorXLSX procesadorXLSX = new ProcesadorXLSX(manejadorContenido, xssfReader);
            procesadorXLSX.process();
        } else {
            InputStream inp = new FileInputStream(archivoExcel);
            libroConveniosPrimaDevengada = WorkbookFactory.create(inp);
            llenaTablaConveniosXLS();
        }
        
        if(!metioRegistroMes) {
            throw new ExcelMalFormadoException(ExcelMalFormadoException.MES_NO_ENCONTRADO, archivoExcel);
        }
    }
    
    public void creaTablaConvenios() throws SQLException {
        st.executeUpdate("DROP TABLE IF EXISTS convenios_pd");
        String sql = "CREATE TABLE convenios_pd (PERIODO INTEGER, ID_AGENTE INTEGER, NOMBRE_AGENTE VARCHAR(250), SISTEMA_ORIGEN VARCHAR(25),"
                + " ID_RAMO_CONTABLE INTEGER, RAMO_CONTABLE VARCHAR(250), ID_SUBRAMO INTEGER, SUBRAMO VARCHAR(250), ID_PROMOTORIA INTEGER,"
                + " PROMOTORIA VARCHAR(250), IMP_PMA_RIESGO_DEV DOUBLE, MARCA INTEGER, RAMO INTEGER, COLUMNA INTEGER) ";
        st.executeUpdate(sql);
    }
    
    public void insertaRegistro(String datos, int renglon) throws SQLException, ExcelMalFormadoException {
        datos = datos.replace("'", "&").replace(",", "&").replace("&", "").trim();
        String[] renglonParseado = preparaRenglon(datos);
        if(renglonParseado != null) {
            validaCampos(renglonParseado, renglon);
            String queryValores = construyeSQLValores(renglonParseado, renglon, tipoFiltroPeriodo, mesSeleccionado, archivoExcel);
            if(queryValores != null) {
                st.execute(queryCampos + queryValores);
                metioRegistroMes = true;
            }
        }
    }
    
    public void llenaTablaConveniosXLS() throws ExcelMalFormadoException, SQLException {
        Sheet hojaConvenios = libroConveniosPrimaDevengada.getSheetAt(0);
        
        Row renglonActual = null;
        for(int j = 1; j < hojaConvenios.getLastRowNum(); j++) {
            renglonActual = hojaConvenios.getRow(j);
            
            if(renglonActual == null) {
                throw new ExcelMalFormadoException(j, 0, ExcelMalFormadoException.RENGLON_VACIO, archivoExcel);
            }
            
            String[] valores = preparaRenglon(construyeRenglon(renglonActual));
            if(valores.length != 12) {
                throw new ExcelMalFormadoException(ExcelMalFormadoException.FALTA_COLUMNA, archivoExcel);
            }
            
            String queryValores =  construyeSQLValores(valores, j, FILTRO_BONOS_CALIDAD, mesSeleccionado, archivoExcel);
            if(queryValores != null) {
                st.executeUpdate(queryCampos + queryValores);
            }
        }
    }
    
    private String construyeRenglon(Row renglon) {      
        String linea = "";
        Cell celdaActual;
        
        for(int i = 0; i < renglon.getLastCellNum(); i++) {
            celdaActual = renglon.getCell(i);
            String campoActual = "";
            
            if(celdaActual == null) {
                linea = linea + "|";
                continue;
            }
            
            boolean eraNumero = true;
            
            if(celdaActual.getCellType() == Cell.CELL_TYPE_STRING) {
                campoActual = celdaActual.getStringCellValue();
                campoActual = campoActual.replace("'", " ").replace(",", " ").replace(" ", "").trim();
                try {
                    Double.parseDouble(campoActual);
                } catch (NumberFormatException nfe) {
                    eraNumero = false;
                }
            
                if(eraNumero) {
                    campoActual = "" + Double.parseDouble(campoActual);
                }
            }
            if(celdaActual.getCellType() == Cell.CELL_TYPE_NUMERIC &&
                    (i == 1 || i == 2 || i == 7 || i == 9)) {
                campoActual = "" + (int) celdaActual.getNumericCellValue();
            } else if(celdaActual.getCellType() == Cell.CELL_TYPE_NUMERIC) {
                campoActual = "" + celdaActual.getNumericCellValue();
            }
            
            campoActual = campoActual.replace("'", " ").replace(",", " ").replace(" ", "").trim();
            
            if(i == renglon.getLastCellNum() - 1) {
                linea = linea + campoActual;
            } else {
                linea = linea + campoActual + "|";
            }
        }
        
        return linea;
    }
    
    public String[] preparaRenglon(String renglon) {
        String[] datosRenglon = new String[INDICES_DATOS_VALIDOS.length];
        String[] datosParseados = renglon.split("\\|");
        
        for(int i = 0; i < INDICES_DATOS_VALIDOS.length; i++) {
            String datoActual = datosParseados[INDICES_DATOS_VALIDOS[i]];
            if(INDICES_DATOS_VALIDOS[i] == 23) {
                if(datoActual.equals("")) {
                    datoActual = "0";
                } else if(datoActual.trim().equals("X")) {
                    datoActual = "1";
                } else if(datoActual.trim().equals("DXP")) {
                    return null;
                }
            }
            datosRenglon[i] = datoActual;
        }
        
        return datosRenglon;
    }
    
    public void validaCampos(String[] campos, int renglon) throws ExcelMalFormadoException {
        //{0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 16, 23};
        //Valida el periodo
        if(campos[0].equals("P_INV")) {
            boolean fin = true;
            for(int i = 1; i < campos.length; i++) {
                fin = fin && campos[i].equals("0");
            }
            if(fin) {
                campos[0] = "0000-00";
                return;
            } else {
                throw new ExcelMalFormadoException(renglon-1, 0, ExcelMalFormadoException.DEVENGADO, archivoExcel);
            }
        }
        
        //Valida id_agente
        try {
            Integer.parseInt(campos[1]);
        } catch(Exception ex) {
            throw new ExcelMalFormadoException(renglon-1, 2, ExcelMalFormadoException.DEVENGADO, archivoExcel);
        } 
        
        //Valida id_ramo_subcontable
        int id_ramo_subc = 0;
        try {
            id_ramo_subc = Integer.parseInt(campos[6]);
        } catch(Exception ex) {
            throw new ExcelMalFormadoException(renglon-1, 7, ExcelMalFormadoException.DEVENGADO, archivoExcel);
        }
        if(!(id_ramo_subc >= 0 && id_ramo_subc <= 36)) {
            throw new ExcelMalFormadoException(renglon-1, 7, ExcelMalFormadoException.DEVENGADO, archivoExcel);
        }
        
        //Valida id_promotoria
        try {
            Integer.parseInt(campos[8]);
        } catch(Exception ex) {
            throw new ExcelMalFormadoException(renglon-1, 12, ExcelMalFormadoException.DEVENGADO, archivoExcel);
        }
        
        //Valida primapagada
        try {
            Double.parseDouble(campos[10]);
        } catch(Exception ex) {
            throw new ExcelMalFormadoException(renglon-1, 22, ExcelMalFormadoException.DEVENGADO, archivoExcel);
        }
    }
    
    public String construyeSQLValores(String[] valores, int renglon, int tipoFiltroPeriodo, int mesSeleccionado, File archivoExcel) throws ExcelMalFormadoException {
        
        String queryValores = " VALUES (";
        int mes = -1;
        try {
            mes =  Integer.parseInt(valores[0].substring(valores[0].length() - 2));
            valores[0] = "" + mes;
        } catch (NumberFormatException nfe) {
            throw new ExcelMalFormadoException(renglon, 0, ExcelMalFormadoException.TIPO_INESPERADO, archivoExcel);
        }
        
        if(mesSeleccionado < mes) {
            return null;
        }

        for(int k = 0; k < valores.length; k++) {
            
            boolean esDouble = true;
            if(valores[k].equals("-")) 
                valores[k] = "" + 0.0;
            
            try {
                Double.parseDouble(valores[k]);
            } catch(NumberFormatException nfe) {
                esDouble = false;
            }
            
            if(esDouble && (INDICES_DATOS_VALIDOS[k] == 16)) {
                queryValores += valores[k] + ",";
            } else {
                boolean esNumero = true;
                try {
                    if(valores[k].length() != 0) {
                        Integer.parseInt("" + (valores[k].charAt(0)));
                    } else {
                        queryValores += "0,";
                        continue;
                    }
                } catch(NumberFormatException nfe) {
                    esNumero = false || (valores[k].charAt(0) == '+' || valores[k].charAt(0) == '-');
                }
                
                try {
                    Integer.parseInt("" + (valores[k].charAt(valores[k].length() - 1)));
                } catch(NumberFormatException nfe) {
                    esNumero = false;
                }
                
                if(esNumero) {
                    queryValores += valores[k].replace(" ", "") + ",";
                } else {
                    queryValores += "'" + valores[k] + "'" + ",";
                }
            }
        }
            
        int ramo = clasificaRamo(valores[3], valores[4], archivoExcel);
        int columna = columnaCorresp(valores[3], valores[4]);
        queryValores += ramo +", "+columna+ ")";
        return queryValores;
    }
    
}